package com.boot.system.service.Impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.boot.framework.common.DropTree;
import com.boot.system.dto.SysDeptDTO;
import com.boot.system.entity.SysDeptEntity;
import com.boot.system.mapper.SysDeptMapper;
import com.boot.system.wrapper.SysDeptWrapper;
import com.boot.system.service.ISysDeptService;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * 系统部门
 *
 * @author yangfan
 * @date 2023-12-25 20:54:40
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDeptEntity> implements ISysDeptService {
    private LambdaQueryWrapper<SysDeptEntity> getQueryWrapper(Map<String, Object> params) {
        LambdaQueryWrapper<SysDeptEntity> wrapper = Wrappers.lambdaQuery(SysDeptEntity.class);
        String name = (String) params.get("name");
        wrapper.like(StrUtil.isNotEmpty(name), SysDeptEntity::getName, name);
        return wrapper;
    }

    @Override
    public List<SysDeptDTO> selectList(Map<String, Object> params) {
        List<SysDeptEntity> deptEntities = baseMapper.selectList(getQueryWrapper(params));
        List<SysDeptDTO> roots = new ArrayList<>();
        Map<String, List<SysDeptDTO>> deptMap = new HashMap<>();
        for (SysDeptEntity sysDeptEntity : deptEntities) {
            if (sysDeptEntity.getParentId().equals("0")) {
                roots.add(SysDeptWrapper.build().entityDTO(sysDeptEntity));
            } else {
                deptMap.computeIfAbsent(sysDeptEntity.getParentId(), k -> new ArrayList<>());
                deptMap.get(sysDeptEntity.getParentId()).add(SysDeptWrapper.build().entityDTO(sysDeptEntity));
            }
        }
        for (SysDeptDTO sysDeptDTO : roots) {
            sysDeptDTO.getChildren().addAll(findChildren(sysDeptDTO.getDeptId(), deptMap));
        }
        return roots;
    }

    @Override
    public List<DropTree> deptTree() {
        List<SysDeptEntity> deptEntities = baseMapper.selectList(Wrappers.emptyWrapper());
        List<DropTree> roots = new ArrayList<>();
        Map<String, List<DropTree>> treeMap = new HashMap<>();
        for (SysDeptEntity sysDept : deptEntities) {
            if (sysDept.getParentId().equals("0")) {
                roots.add(buildDropTree(sysDept));
            } else {
                treeMap.computeIfAbsent(sysDept.getParentId(), k -> new ArrayList<>());
                treeMap.get(sysDept.getParentId()).add(buildDropTree(sysDept));
            }
        }
        for (DropTree treeList : roots) {
            treeList.getChildren().addAll(findTreeChildren(treeList.getId(), treeMap));
        }
        return roots;
    }

    private List<DropTree> findTreeChildren(String parentId, Map<String, List<DropTree>> treeMap) {
        List<DropTree> dropTrees = treeMap.get(parentId);
        if (Objects.isNull(dropTrees)) {
            return new ArrayList<>();
        }
        for (DropTree treeList : dropTrees) {
            treeList.getChildren().addAll(findTreeChildren(treeList.getId(), treeMap));
        }
        return dropTrees;
    }

    private List<SysDeptDTO> findChildren(String parentId, Map<String, List<SysDeptDTO>> deptMap) {
        List<SysDeptDTO> sysDeptDTOS = deptMap.get(parentId);
        if (Objects.isNull(sysDeptDTOS)) {
            return new ArrayList<>();
        }
        for (SysDeptDTO sysDeptDTO : sysDeptDTOS) {
            sysDeptDTO.getChildren().addAll(findChildren(sysDeptDTO.getDeptId(), deptMap));
        }
        return sysDeptDTOS;
    }

    private DropTree buildDropTree(SysDeptEntity sysDept) {
        DropTree treeList = new DropTree();
        treeList.setId(sysDept.getDeptId());
        treeList.setLabel(sysDept.getName());
        treeList.setValue(sysDept.getDeptId());
        treeList.setParentId(sysDept.getParentId());
        return treeList;
    }
}